package com.gulimall.product.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.gulimall.common.constant.ProductConstant;
import com.gulimall.common.to.SkuReductionTo;
import com.gulimall.common.to.SpuBoundsTo;
import com.gulimall.common.utils.R;
import com.gulimall.product.entity.*;
import com.gulimall.product.feign.CouponFeignService;
import com.gulimall.product.feign.SearchFeignService;
import com.gulimall.product.feign.WareFeignService;
import com.gulimall.product.resp.AttrRespVo;
import com.gulimall.product.service.*;
import com.gulimall.product.to.es.SkuEsModelTo;
import com.gulimall.product.to.ware.SkuHasStockTo;
import com.gulimall.product.vo.spusavevo.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gulimall.common.utils.PageUtils;
import com.gulimall.common.utils.Query;

import com.gulimall.product.dao.SpuInfoDao;
import org.springframework.transaction.annotation.Transactional;


@Service("spuInfoService")
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {
    @Autowired
    private AttrService attrService;
    @Autowired
    private BrandService brandService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private SkuInfoService skuInfoService;
    @Autowired
    private SkuImagesService skuImagesService;
    @Autowired
    private SpuImagesService spuImagesService;
    @Autowired
    private SpuInfoDescService spuInfoDescService;
    @Autowired
    private ProductAttrValueService productAttrValueService;
    @Autowired
    private SkuSaleAttrValueService skuSaleAttrValueService;
    @Autowired
    private CouponFeignService couponFeignService;
    @Autowired
    private WareFeignService wareFeignService;
    @Autowired
    private SearchFeignService searchFeignService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                new QueryWrapper<SpuInfoEntity>()
        );

        return new PageUtils(page);
    }

    @Transactional
    @Override
    public void saveSpuInfo(SpuSaveVo spuInfoVo) {
        // 1、保存spu的基本数据 pms_spu_info
        //创建商品信息的对象 用于保存基本数据
        SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
        //将vo中的数据拷贝到spuInfoEntity中
        BeanUtils.copyProperties(spuInfoVo, spuInfoEntity);
        //额外将spuInfoEntity对象中的创建时间和最后修改时间进行赋值
        spuInfoEntity.setCreateTime(new Date());
        spuInfoEntity.setUpdateTime(new Date());
        //调用方法进行保存商品基本信息
        this.saveBaseSpuInfo(spuInfoEntity);

        //提取spuId
        Long spuId = spuInfoEntity.getId();

        // 2、保存spu的描述图片 pms_spu_info_desc
        List<String> decript = spuInfoVo.getDecript();
        if (decript != null && decript.size() > 0) {
            SpuInfoDescEntity spuInfoDescEntity = new SpuInfoDescEntity();
            spuInfoDescEntity.setSpuId(spuId);
            spuInfoDescEntity.setDecript(String.join(",", decript));
            spuInfoDescService.saveSpuInfoDesc(spuInfoDescEntity);
        }

        // 3、保存spu的图片集 pms_spu_images
        List<String> images = spuInfoVo.getImages();
        if (images != null && images.size() > 0) {
            List<SpuImagesEntity> spuImagesEntities = images.stream().map(image -> {
                SpuImagesEntity spuImagesEntity = new SpuImagesEntity();
                //商品编号
                spuImagesEntity.setSpuId(spuId);
                //商品图片名称，截取最后一个下划线后面的所有
                spuImagesEntity.setImgName(StringUtils.substringAfterLast(image, "_"));
                //图片路径
                spuImagesEntity.setImgUrl(image);
                return spuImagesEntity;
            }).collect(Collectors.toList());

            spuImagesService.saveSpuImages(spuImagesEntities);
        }

        // 4、保存spu的规格参数 pms_product_attr_value
        List<BaseAttrs> baseAttrs = spuInfoVo.getBaseAttrs();
        List<ProductAttrValueEntity> productAttrValueEntityList = baseAttrs.stream().map(attr -> {
            ProductAttrValueEntity productAttrValueEntity = new ProductAttrValueEntity();
            productAttrValueEntity.setSpuId(spuId);
            productAttrValueEntity.setAttrId(attr.getAttrId());
            productAttrValueEntity.setAttrValue(attr.getAttrValues());
            productAttrValueEntity.setQuickShow(attr.getShowDesc());
            //根据属性id查询属性信息
            AttrRespVo attrInfo = attrService.getAttrInfo(attr.getAttrId());
            productAttrValueEntity.setAttrName(attrInfo.getAttrName());
            //是否参与检索
            productAttrValueEntity.setSearchType(attrInfo.getSearchType());

            return productAttrValueEntity;
        }).collect(Collectors.toList());
        productAttrValueService.saveProductAttrValues(productAttrValueEntityList);

        // 5、保存spu的积分信息 gulimall_sms -> sms_spu_bounds
        //获取积分信息
        Bounds bounds = spuInfoVo.getBounds();
        //copy到To传输对象中
        SpuBoundsTo spuBoundsTo = new SpuBoundsTo();
        spuBoundsTo.setSpuId(spuId);
        BeanUtils.copyProperties(bounds, spuBoundsTo);
        //调用远程服务进行保存coupon
        R r = couponFeignService.saveSpuBounds(spuBoundsTo);
        if (r.getCode() != 0) {
            log.error("远程保存积分信息失败！！！！！！！！");
        }

        // 6、保存当前spu对应的所有的sku信息：
        // 6.1、sku的基本信息 pms_sku_info
        List<Skus> skus = spuInfoVo.getSkus();
        if (skus != null && skus.size() > 0) {
            skus.forEach(sku -> {
                String defaultImg = "";
                for (Images image : sku.getImages()) {
                    if (image.getDefaultImg() == 1) {
                        defaultImg = image.getImgUrl();
                    }
                }

                SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
                skuInfoEntity.setSpuId(spuId);
                //skuInfoEntity.setPrice(sku.getPrice());
                //skuInfoEntity.setSkuName(sku.getSkuName());
                //skuInfoEntity.setSkuTitle(sku.getSkuTitle());
                //skuInfoEntity.setSkuSubtitle(sku.getSkuSubtitle());
                //上面四行代码使用下面这一行代码进行替换
                BeanUtils.copyProperties(sku, skuInfoEntity);
                skuInfoEntity.setBrandId(spuInfoEntity.getBrandId());
                skuInfoEntity.setCatalogId(spuInfoEntity.getCatalogId());
                //将商品的描述也添加到sku的描述中
                skuInfoEntity.setSkuDesc(spuInfoEntity.getSpuDescription());
                //商品销售量的初始值 默认为0
                skuInfoEntity.setSaleCount(0L);
                skuInfoEntity.setSkuDefaultImg(defaultImg);
                //保存sku基本信息
                skuInfoService.saveSkuInfo(skuInfoEntity);

                //提取保存的skuId
                Long skuId = skuInfoEntity.getSkuId();

                // 6.2、sku的图片信息 pms_sku_images
                List<SkuImagesEntity> skuImagesEntityList = sku.getImages().stream().map(image -> {
                    SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
                    skuImagesEntity.setSkuId(skuId);
                    skuImagesEntity.setImgUrl(image.getImgUrl());
                    skuImagesEntity.setDefaultImg(image.getDefaultImg());
                    return skuImagesEntity;
                }).filter(image -> {
                    //需要对图片的路径进行过滤，没有路径的不进行收集
                    return StringUtils.isNotEmpty(image.getImgUrl());
                }).collect(Collectors.toList());
                skuImagesService.saveSkuImages(skuImagesEntityList);

                // 6.3、sku的销售属性信息 pms_sku_sale_attr_value
                List<SkuSaleAttrValueEntity> skuSaleAttrValueEntityList = sku.getAttr().stream().map(attr -> {
                    SkuSaleAttrValueEntity skuSaleAttrValueEntity = new SkuSaleAttrValueEntity();
                    BeanUtils.copyProperties(attr, skuSaleAttrValueEntity);
                    skuSaleAttrValueEntity.setSkuId(skuId);
                    return skuSaleAttrValueEntity;
                }).collect(Collectors.toList());
                skuSaleAttrValueService.saveSkuSaleAttrValues(skuSaleAttrValueEntityList);

                // 6.4、sku的优惠满减等信息：
                // 6.4.1、商品优惠信息：gulimall_sms -> sms_sku_ladder
                // 6.4.2、商品满减信息：gulimall_sms -> sms_sku_full_reduction
                // 6.4.3、会员价格信息：gulimall_sms -> sms_member_price
                //调用一次远程服务完成以上三个功能
                SkuReductionTo skuReductionTo = new SkuReductionTo();
                skuReductionTo.setSkuId(skuId);
                BeanUtils.copyProperties(sku, skuReductionTo);
                if (skuReductionTo.getFullCount() > 0 || skuReductionTo.getFullPrice().compareTo(new BigDecimal("0")) == 1) {
                    R r1 = couponFeignService.saveSkuReduction(skuReductionTo);
                    if (r1.getCode() != 0) {
                        log.error("远程保存优惠信息失败！！！！！！！！");
                    }
                }
            });
        }
    }

    /**
     * 保存商品的基本信息
     *
     * @param spuInfoEntity
     */
    @Override
    public void saveBaseSpuInfo(SpuInfoEntity spuInfoEntity) {
        this.baseMapper.insert(spuInfoEntity);
    }

    /**
     * spu管理页面的检索接口
     * 根据分类、品牌、状态、关键字、分页进行检索
     *
     * @param params
     * @return
     */
    @Override
    public PageUtils queryPageByCondition(Map<String, Object> params) {
        QueryWrapper<SpuInfoEntity> queryWrapper = new QueryWrapper<>();
        //关键字key 检索商品名称以及商品描述的模糊检索
        String key = (String) params.get("key");
        if (StringUtils.isNotEmpty(key)) {
            queryWrapper.and((wrapper) -> {
                wrapper.like("spu_name", key).or().like("spu_description", key);
            });
        }

        //根据分类进行检索 catelogId
        String catelogId = (String) params.get("catelogId");
        if (StringUtils.isNotEmpty(catelogId) && !"0".equals(catelogId)) {
            queryWrapper.eq("catalog_id", catelogId);
        }

        //根据品牌进行检索 brandId
        String brandId = (String) params.get("brandId");
        if (StringUtils.isNotEmpty(brandId) && !"0".equals(brandId)) {
            queryWrapper.eq("brand_id", brandId);
        }

        //商品状态
        String status = (String) params.get("status");
        if (StringUtils.isNotEmpty(status)) {
            queryWrapper.eq("publish_status", status);
        }


        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                queryWrapper
        );

        return new PageUtils(page);
    }

    /**
     * 商品上架功能接口
     * 1、根据当前spuId查询所有的sku信息
     * 2、根据查到的所有sku对要传入到es中的数据模型进行数据对拷，把数据存入到数据模型中
     * 3、
     *
     * @param spuId
     */
    @Override
    public void spuUp(Long spuId) {
        //查出当前spuId对应的所有的sku信息
        List<SkuInfoEntity> skus = skuInfoService.getSkusBySpuId(spuId);

        //查询当前sku的所有可以用来检索的属性（因同一个spu下的sku都是一样的，可以只根据spuId进行查询一次，减少与数据库的交互）
        List<ProductAttrValueEntity> productAttrValueEntityList = productAttrValueService.list(
                new QueryWrapper<ProductAttrValueEntity>() {{
                    eq("spu_id", spuId).eq("search_type", ProductConstant.AttrEnum.IS_SEARCH_TYPE.getCode());
                }}
        );
        List<SkuEsModelTo.Attr> skuEsModelAttrs = null;
        if (productAttrValueEntityList.size() > 0) {
            skuEsModelAttrs = productAttrValueEntityList.stream().map(item -> {
                SkuEsModelTo.Attr attr = new SkuEsModelTo.Attr();
                BeanUtils.copyProperties(item, attr);
                return attr;
            }).collect(Collectors.toList());
        }

        //收集skuIds
        List<Long> skuIds = skus.stream().map(sku -> {
            return sku.getSkuId();
        }).collect(Collectors.toList());
        //需要调用远程仓储服务进行查询该sku的库存信息
        Map<Long, Boolean> skusHasStockMap = null;
        try {
            R skusHasStock = wareFeignService.getSkusHasStock(skuIds);
            TypeReference<List<SkuHasStockTo>> listTypeReference = new TypeReference<List<SkuHasStockTo>>(){};
            skusHasStockMap = skusHasStock.getData(listTypeReference).stream()
                    .collect(Collectors.toMap(SkuHasStockTo::getSkuId, item -> item.getHasStock()));
        } catch (Exception e) {
            log.error("库存服务调用异常：异常原因{}", e);
        }

        Map<Long, Boolean> finalSkusHasStockMap = skusHasStockMap;
        List<SkuEsModelTo.Attr> finalSkuEsModelAttrs = skuEsModelAttrs;

        //收集需要存储到es中的数据
        List<SkuEsModelTo> skuEsModelToList = skus.stream().map(sku -> {
            //组装需要的数据
            SkuEsModelTo skuEsModelTo = new SkuEsModelTo();
            BeanUtils.copyProperties(sku, skuEsModelTo);

            //将以下不能进行属性对拷的数据进行单独赋值
            skuEsModelTo.setSkuImg(sku.getSkuDefaultImg());
            skuEsModelTo.setSkuPrice(sku.getPrice());
            //将sku热度默认设置为0
            skuEsModelTo.setHotScore(0L);

            //用skuId获取map集合中的值,如果因异常导致没有获取到库存信息，默认赋值为有库存
            if (finalSkusHasStockMap == null) {
                skuEsModelTo.setHasStock(true);
            } else {
                skuEsModelTo.setHasStock(finalSkusHasStockMap.get(sku.getSkuId()));
            }

            //查询品牌相关信息
            BrandEntity brand = brandService.getById(sku.getBrandId());
            skuEsModelTo.setBrandName(brand.getName());
            skuEsModelTo.setBrandImg(brand.getLogo());
            //查询分类相关信息
            CategoryEntity category = categoryService.getById(sku.getCatalogId());
            skuEsModelTo.setCatalogName(category.getName());

            //组装attrs
            skuEsModelTo.setAttrs(finalSkuEsModelAttrs);

            return skuEsModelTo;
        }).collect(Collectors.toList());

        //将数据发送给es微服务进行保存
        R r = searchFeignService.productStatusUp(skuEsModelToList);
        if (r.getCode() == 0) {
            //调用成功后//修改所上架的产品状态为上架状态
            SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
            spuInfoEntity.setId(spuId);
            spuInfoEntity.setPublishStatus(ProductConstant.StatusEnum.SPU_UP.getCode());
            spuInfoEntity.setUpdateTime(new Date());
            baseMapper.updateById(spuInfoEntity);
        } else {
            //远程调用失败
        }
    }
}